home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Jumpstart / Multimedia Microsoft Jumpstart Version 1.1a (Microsoft).BIN / develpmt / examples / infobrws / src / playvfw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-20  |  35.7 KB  |  925 lines

  1. //     (C) Copyright Microsoft Corp. 1991.  All rights reserved.
  2. //
  3. //     You have a royalty-free right to use, modify, reproduce and 
  4. //     distribute the Sample Files (and/or any modified version) in 
  5. //     any way you find useful, provided that you agree that 
  6. //     Microsoft has no warranty obligations or liability for any 
  7. //     Sample Application Files which are modified. 
  8.  
  9.  
  10. /****************************************************************************
  11.  
  12.     MODULE    : PLAYVFW.C
  13.  
  14.     PURPOSE   : This application implements Video For Windows and Audio playback in an interactive and 
  15.                 configurable manner.  The program reads several ini files to get position information as
  16.                 well as file names for the VFW and audio files.  These ini files are completely configurable
  17.                 by the end user.
  18.  
  19.     FUNCTIONS :  
  20.                  
  21.                 PlayVFWWinProc
  22.                 WinMain
  23.                 Transition
  24.  
  25.     COMMENTS  : 
  26.  
  27.     HISTORY   : Created by Steven Molstad 8/12/93
  28.  
  29. ****************************************************************************/
  30.  
  31. #include "windows.h"
  32. #include <stdlib.h>
  33. #include "playvfw.h"
  34. #include "proto.h"
  35. #include "mmsystem.h"
  36. #include <digitalv.h>
  37. #include <stdio.h>
  38. #include <time.h>  
  39. #include <viewer.h>
  40.  
  41.  
  42.  
  43. /****************************************************************************
  44.  
  45.     FUNCTION  : WinMain( HANDLE, HANDLE, LPSTR, int )
  46.  
  47.     PURPOSE   : This function is where are the application initialization occurs.  The main window
  48.                 for the application is created here as well as global memory for the device structures.
  49.                 The cursors are loaded and the startup screen bitmap is loaded from the resource file. This
  50.                 Function also contains the main message loop for the application.
  51.     
  52.     COMMENTS  : 
  53.  
  54.     HISTORY   : Created by Steven Molstad 6/1/93
  55.  
  56. ****************************************************************************/
  57.  
  58. int PASCAL WinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow )
  59. HANDLE hInstance, hPrevInstance;
  60. LPSTR lpszCmdLine;
  61. int cmdShow;
  62. {
  63.     MSG   msg;
  64.     HWND  hWnd;
  65.     
  66.      HDC hDC;
  67.      HDC hdcMemory;
  68.      HBITMAP hbmpMyBitmap, hbmpOld,hbmpMyBitmap2;
  69.      BITMAP bm;     
  70.      RECT Points;
  71.      
  72.     if (!hPrevInstance) {
  73.     /* Call initialization procedure if this is the first instance */
  74.     if (!PlayVFWInit( hInstance ))
  75.         return FALSE;
  76.     }
  77.     else       
  78.         {
  79.         MessageBox(NULL,"Can only run one instance of this application","ERROR",MB_OK);
  80.         return FALSE;
  81.         }
  82.      
  83.      // Check to see if we are running NT, if we are shut the program down.
  84.      
  85.      if (fNTRunning())
  86.           {
  87.           MessageBox(NULL,"Cannot run this application under NT","ERROR",MB_OK);
  88.           return FALSE;
  89.           }
  90.       
  91.       // Check to see if we are running in a supported Resolution and support color mode.  If we are not
  92.       // warn the user that he may not get the best results.
  93.       
  94.       if (!fHiResCapable())
  95.             if (!fVgaCapable() || !f256Capable())
  96.                  MessageBox(NULL,"For best results use either 1024 X 768 >= 256 color mode or 640 X 480 >= 256 color mode","Note:",MB_OK);
  97.                   
  98.       // Check to see if there is a sound device if not stop all calls to the sound API otherwise call them.
  99.       // This way we don't crash when there is no sound device.            
  100.                   
  101.       if (!cNumAudio())
  102.            bNoSound=TRUE;
  103.       else
  104.            bNoSound=FALSE;      
  105.        
  106.        
  107.      
  108.                                                                 
  109.     // Allocate memory for each of the different devices (owner draw buttons).  This program contains up 
  110.     // to 8 different devices which can be active at any given time.  A device structure describes the
  111.     // different attributes of an owner draw button.  For example the device ID of the AVI file displayed
  112.     // in the owner draw button is stored in the hDevice structure.
  113.     
  114.                                                           
  115.     hDevice1=GlobalAlloc(GHND,sizeof(DEVICESTRUCT));
  116.     hDevice2=GlobalAlloc(GHND,sizeof(DEVICESTRUCT));
  117.     hDevice3=GlobalAlloc(GHND,sizeof(DEVICESTRUCT));
  118.     hDevice4=GlobalAlloc(GHND,sizeof(DEVICESTRUCT));
  119.     hDevice5=GlobalAlloc(GHND,sizeof(DEVICESTRUCT));
  120.     hDevice6=GlobalAlloc(GHND,sizeof(DEVICESTRUCT));
  121.     hDevice7=GlobalAlloc(GHND,sizeof(DEVICESTRUCT));
  122.     hDevice8=GlobalAlloc(GHND,sizeof(DEVICESTRUCT));
  123.     hDevice9=GlobalAlloc(GHND,sizeof(DEVICESTRUCT));   
  124.     
  125.     hDirs=GlobalAlloc(GHND,sizeof(DIRSTRUCT));
  126.     
  127.                              
  128.     // make sure all of the memory was allocated.  If not drop out of the program.                          
  129.                               
  130.     if (!hDevice1 && !hDevice2 && !hDevice3 && !hDevice4 && !hDevice5 && !hDevice6 && !hDevice7 && !hDevice8 && !hDevice9 && !hDirs)
  131.     {
  132.      MessageBox(NULL,"The Initial memory allocation failed aborting program","ERROR",MB_OK);
  133.      return FALSE;
  134.     }
  135.                                                                                   
  136.     // lock all the memory once so it can be used in the rest of the program.                                                                              
  137.  
  138.     lpDevice1=(LPDEVICESTRUCT)GlobalLock(hDevice1);
  139.     lpDevice2=(LPDEVICESTRUCT)GlobalLock(hDevice2);
  140.     lpDevice3=(LPDEVICESTRUCT)GlobalLock(hDevice3);
  141.     lpDevice4=(LPDEVICESTRUCT)GlobalLock(hDevice4);
  142.     lpDevice5=(LPDEVICESTRUCT)GlobalLock(hDevice5);
  143.     lpDevice6=(LPDEVICESTRUCT)GlobalLock(hDevice6);
  144.     lpDevice7=(LPDEVICESTRUCT)GlobalLock(hDevice7);
  145.     lpDevice8=(LPDEVICESTRUCT)GlobalLock(hDevice8);
  146.     lpDevice9=(LPDEVICESTRUCT)GlobalLock(hDevice9);
  147.     
  148.     
  149.     lpDirs=(LPDIRSTRUCT)GlobalLock(hDirs);  
  150.                                                                            
  151.     // Make sure that the memory could be locked.                                                                         
  152.                                                                              
  153.     if (!lpDevice1 && !lpDevice2 && !lpDevice3 && !lpDevice4 && !lpDevice5 && !lpDevice6 && !lpDevice7 && !lpDevice8 && !lpDevice9 && !lpDirs)
  154.           {
  155.            MessageBox(NULL,"The Initial memory lock failed aborting program","ERROR",MB_OK);
  156.            return FALSE;
  157.           }
  158.                                                  
  159.                                                  
  160.     hWnd = CreateWindow((LPSTR)szAppName,
  161.             (LPSTR)szMessage,
  162.             WS_OVERLAPPED | WS_MAXIMIZE,
  163.             CW_USEDEFAULT,      /*  x - ignored for tiled windows */
  164.             CW_USEDEFAULT,      /*  y - ignored for tiled windows */
  165.             CW_USEDEFAULT,      /* cx - ignored for tiled windows */
  166.             CW_USEDEFAULT,      /* cy - ignored for tiled windows */
  167.             (HWND)NULL,        /* no parent */
  168.             (HMENU)NULL,       /* use class menu */
  169.             (HANDLE)hInstance, /* handle to window instance */
  170.             (LPSTR)NULL        /* no params to pass on */
  171.             );
  172.  
  173.  
  174.     hWndMain=hWnd; 
  175.         
  176.     bButtonDown=FALSE;
  177.     hOld=0;
  178.  
  179.     /* Save instance handle for DialogBox */
  180.     hInst = hInstance;
  181.  
  182.  
  183.    // Load a cursor for each window.
  184.  
  185.     lpDevice1->hCursor=LoadCursor( hInstance, MAKEINTRESOURCE(BUTTON1CURSOR) );
  186.     lpDevice2->hCursor=LoadCursor( hInstance, MAKEINTRESOURCE(BUTTON2CURSOR) );
  187.     lpDevice3->hCursor=LoadCursor( hInstance, MAKEINTRESOURCE(BUTTON3CURSOR) );
  188.     lpDevice4->hCursor=LoadCursor( hInstance, MAKEINTRESOURCE(BUTTON4CURSOR) );
  189.     lpDevice5->hCursor=LoadCursor( hInstance, MAKEINTRESOURCE(BUTTON5CURSOR) );
  190.     lpDevice6->hCursor=LoadCursor( hInstance, MAKEINTRESOURCE(BUTTON6CURSOR) );
  191.  
  192.     hHelloCursor=LoadCursor( NULL, IDC_ARROW );
  193.  
  194.     hWndButtonBar=0; 
  195.  
  196.     
  197.     // The following code loads a bitmap from the resource file and displays it centered on 
  198.     // on the page. 
  199.      
  200.     hbmpMyBitmap = LoadBitmap(hInst, "newlogo");
  201.     GetObject(hbmpMyBitmap, sizeof(BITMAP), &bm);
  202.  
  203.     hDC = GetDC(hWnd);
  204.     hdcMemory = CreateCompatibleDC(hDC);
  205.     hbmpOld = SelectObject(hdcMemory, hbmpMyBitmap);
  206.     GetClientRect(hWnd,&Points);
  207.     
  208.     BmpPoints.left=(Points.right/2)-(bm.bmWidth/2);
  209.     BmpPoints.top=(Points.bottom/2)-(bm.bmHeight/2); 
  210.     
  211.     /* Make window visible according to the way the app is activated */
  212.      
  213.     
  214.     ShowWindow( hWnd, SW_MAXIMIZE );
  215.     UpdateWindow( hWnd ); 
  216.       
  217.     
  218.     // Display the bitmap in the window.  Then delete the bitmap object as well as the 
  219.     // Device context.               
  220.                    
  221.     BitBlt(hDC, (BmpPoints.left), (BmpPoints.top), bm.bmWidth, bm.bmHeight, hdcMemory, 0, 0, SRCCOPY);
  222.     
  223.     SelectObject(hdcMemory, hbmpOld);
  224.  
  225.     DeleteDC(hdcMemory);
  226.  
  227.     ReleaseDC(hWnd, hDC);
  228.     
  229.     DeleteObject(hbmpMyBitmap); 
  230.     
  231.     // load the next bitmap and then initialize the windows and devices.  In this manner
  232.     // the first bitmap will stay up while the setup of the program is happening.  Then
  233.     // we blit the second bitmap and play the VFW file.
  234.      
  235.     hbmpMyBitmap2 = LoadBitmap(hInst, "vgalogo4");
  236.     GetObject(hbmpMyBitmap2, sizeof(BITMAP), &bm);
  237.      
  238.     DeleteObject(hbmpMyBitmap2);    
  239.     
  240.     GetClientRect(hWnd,&Points);
  241.     
  242.     BmpPoints.left=(Points.right/2)-(bm.bmWidth/2);
  243.     BmpPoints.top=(Points.bottom/2)-(bm.bmHeight/2);  
  244.     
  245.      // retrieve the Video For Windows information as well as the audio information from the 
  246.     // initialization files.     
  247.     
  248.     if(!InitVFWStuff(hWnd,hInstance))
  249.          return FALSE;
  250.       
  251.     // Nuke the old bitmap by PatBlt BLACKNESS to the full screen.  
  252.       
  253.     hDC = GetDC(hWnd);  
  254.     
  255.     GetClientRect(hWnd, &Points);
  256.  
  257.     PatBlt(hDC, Points.left, Points.top,
  258.            Points.right, Points.bottom, BLACKNESS);
  259.  
  260.     
  261.     ReleaseDC(hWnd, hDC);
  262.     
  263.     // The following code loads a bitmap from the resource file and displays it centered on 
  264.     // on the page. 
  265.      
  266.     hbmpMyBitmap = LoadBitmap(hInst, "vgalogo4");
  267.     GetObject(hbmpMyBitmap, sizeof(BITMAP), &bm);
  268.  
  269.     hDC = GetDC(hWnd);
  270.     hdcMemory = CreateCompatibleDC(hDC);
  271.     hbmpOld = SelectObject(hdcMemory, hbmpMyBitmap);
  272.     GetClientRect(hWnd,&Points);
  273.     
  274.     BmpPoints.left=(Points.right/2)-(bm.bmWidth/2);
  275.     BmpPoints.top=(Points.bottom/2)-(bm.bmHeight/2); 
  276.     
  277.                       
  278.     // Display the bitmap in the window.  Then delete the bitmap object as well as the 
  279.     // Device context.               
  280.                    
  281.     BitBlt(hDC, (BmpPoints.left), (BmpPoints.top), bm.bmWidth, bm.bmHeight, hdcMemory, 0, 0, SRCCOPY);
  282.     
  283.     SelectObject(hdcMemory, hbmpOld);
  284.  
  285.     DeleteDC(hdcMemory);
  286.  
  287.     ReleaseDC(hWnd, hDC);
  288.     
  289.    
  290.     DeleteObject(hbmpMyBitmap);    
  291.     
  292.     /* Polling messages from event queue */    
  293.     
  294.     // hWndButtonBar is the handle to the modeless dialog box which I use as the Video Control bar.
  295.     
  296.     while (GetMessage((LPMSG)&msg, NULL, 0, 0)) 
  297.          {
  298.          if (hWndButtonBar==0 || !IsDialogMessage(hWndButtonBar,&msg))
  299.               {
  300.                TranslateMessage((LPMSG)&msg);
  301.                DispatchMessage((LPMSG)&msg);
  302.                }
  303.          }
  304.  
  305.     return (int)msg.wParam;
  306. }
  307.  
  308.  /****************************************************************************
  309.  
  310.     FUNCTION  :  PlayVFWWndProc( HWND, unsigned, WORD, LONG)
  311.  
  312.     PURPOSE   :  This is the main Window procedure.  This is where the work takes place. 
  313.  
  314.     COMMENTS  :  There are several messages that have to do with the use of owner draw buttons.  If I
  315.                  was to do it all over I would have probably used Windows VS owner draw buttons.  This
  316.                  would of excluded the need to use WM_PARENTNOTIFY, WM_SETCURSOR, WM_DRAWITEM messages.  
  317.                  Instead I could have had an individual window procedure for each child window that would have
  318.                  handled the equivalents to these messages more gracefully.  For example I would have
  319.                  just handled the WM_RBUTTONDOWN in the child window procedure vs having to look for
  320.                  WM_PARENTNOTIFY in the parents window procedure.
  321.  
  322.  
  323.     HISTORY   :  created by Steven Molstad 6/1/93
  324.  
  325. ****************************************************************************/
  326.  
  327. /* Procedures which make up the window class. */   
  328.  
  329. long FAR PASCAL PlayVFWWndProc( hWnd, message, wParam, lParam )
  330. HWND hWnd;
  331. unsigned message;
  332. WORD wParam;
  333. LONG lParam;
  334. {
  335.  
  336.     WORD wCurrentDevice;
  337.     
  338.     int uixPos;
  339.     int uiyPos;
  340.     WORD fActive;  
  341.     int count;
  342.     HPALETTE hpal, hPalPrevious;
  343.     HDC hdc;
  344.  
  345.     switch (message)
  346.     {
  347.     case WM_CREATE:
  348.          VWRGlobal=0;
  349.     break;
  350.  
  351.     case WM_SYSCOMMAND:
  352.           switch (wParam)
  353.                 {
  354.  
  355.                  default:
  356.                        return DefWindowProc( hWnd, message, wParam, lParam );
  357.  
  358.                 }
  359.     break;
  360.  
  361.     case WM_COMMAND:
  362.     break;
  363.  
  364.   
  365.     // This message is sent to the parent window of an Owner Draw button when some action is taken in 
  366.     // that owner draw button.  The action I am looking for is a Left Button Down message.  Since the 
  367.     // Owner draw button has its own window procedure the WM_LBUTTONDOWN message will not be directly 
  368.     // sent to the parents window procedure.  Inderectly windows sends a WM_PARENTNOTIFY message. 
  369.      
  370.     case WM_PARENTNOTIFY:
  371.  
  372.     // When we recieve a WM_PARENTNOTIFY message the action that was taken is represented in the wParam.
  373.     // We are looking for a Left Button click, for simplicity all we care about is that the button was
  374.     // pressed.
  375.                               
  376.           if (wParam==WM_LBUTTONDOWN)
  377.                  {    
  378.            // Grab the X and Y position of the Mouse cursor which is stored in the high and low word of
  379.            // the lParam.  This postion will help determine which button the cursor was over when the
  380.            // mouse button was depressed.
  381.           
  382.                   uixPos=LOWORD(lParam);
  383.                   uiyPos=HIWORD(lParam);
  384.                   
  385.                   // The transition function creates, displays and plays the morph video.  
  386.                   // It also takes care of displaying the second page as well as playing
  387.                   // back the audio associated with the morph.
  388.                                          
  389.                   if(Transition(lpDevice1,uixPos,uiyPos,1))
  390.                         return FALSE;            
  391.            
  392.                   if(Transition(lpDevice2,uixPos,uiyPos,2))               
  393.                         return FALSE;
  394.             
  395.                   if(Transition(lpDevice3,uixPos,uiyPos,3))               
  396.                         return FALSE;
  397.                 
  398.                   if(Transition(lpDevice4,uixPos,uiyPos,4))               
  399.                          return FALSE;
  400.                 
  401.                   if(Transition(lpDevice5,uixPos,uiyPos,5))               
  402.                          return FALSE;                       
  403.                 
  404.                   if(Transition(lpDevice6,uixPos,uiyPos,6))               
  405.                         return FALSE;   
  406.                         
  407.                   // If this is the first page and the right mouse button was pressed over the 
  408.                   // video window, transition to the 2nd page.      
  409.                   
  410.                   if (bIsPage0)
  411.                        DoPage1(); 
  412.                       
  413.                  } // end of if wParam == WM_RBUTTONDOWN 
  414.           
  415.          if (wParam==WM_RBUTTONDOWN)
  416.                  {
  417.                  
  418.                   // If we are on the last page and someone clicks the right mouse button
  419.                   // close the application.  To recieve this message the cursor must be
  420.                   // over one of the 4 buttons.
  421.                   
  422.                   //if (bIsPage2) 
  423.                   PostMessage(hWndMain,WM_CLOSE,0,0L); 
  424.                   }  
  425.           
  426.          return FALSE;
  427.     break;
  428.     
  429.     
  430.     case WM_LBUTTONDOWN:  
  431.          if (lstrlen(lpDevice1->szFileName)) 
  432.               {
  433.              
  434.                                                       
  435.                if (bIsPage2)
  436.                     {          
  437.                     
  438.                     // kill viewer when a left mouse button is pressed in the main window.
  439.                     
  440.                      if (VWRGlobal)
  441.                            {
  442.                             VwrQuit(VWRGlobal);
  443.                             VWRGlobal=0;
  444.                             }
  445.                      
  446.                       // Stop the Video.  Hide the Viewer window and show the buttons to avoid any
  447.                       // nasty palette changes. 
  448.                                                                           
  449.                       StopVFWFile(lpDevice9->wDeviceID); 
  450.                           
  451.                           
  452.                       ShowWindow(lpDevice9->hWnd, SW_HIDE );
  453.                       ShowWindow(lpDevice1->hWnd, SW_SHOWNORMAL );
  454.                       ShowWindow(lpDevice2->hWnd, SW_SHOWNORMAL );
  455.                       ShowWindow(lpDevice3->hWnd, SW_SHOWNORMAL );
  456.                       ShowWindow(lpDevice4->hWnd, SW_SHOWNORMAL );   
  457.                       ShowWindow( hWndButtonBar, SW_HIDE );
  458.                           
  459.                       SeekAllToStart(); 
  460.                          
  461.  
  462.                          
  463.                           }
  464.                    // }
  465.                }     
  466.              
  467.     break;
  468.     
  469.     case MM_MCINOTIFY:
  470.  
  471.     /* This is where we check the status of an AVI  */
  472.     /* movie that might have been playing.  We do   */
  473.     /* the play with MCI_NOTIFY on so we should get */
  474.     /* a MCI_NOTIFY_SUCCESSFUL if the play        */
  475.     /* completes on it's own.                       */
  476.  
  477.           switch(wParam)
  478.                 {
  479.                  case MCI_NOTIFY_SUCCESSFUL:
  480.                        {
  481.                                   
  482.                         // get the ID of the device which the notify is for.  This value is
  483.                         // stored in the LOWORD of the lParam.
  484.                                   
  485.                         wCurrentDevice=LOWORD(lParam);
  486.                         
  487.                         // Seek all of the AVI movies to the begining frame.
  488.                         
  489.                         SeekVFWToStart(wCurrentDevice);
  490.  
  491.                                                                             
  492.                         // Look for the device which this notify message was meant for.  If
  493.                         // that device is playing, keep it playing.  The bVideoPlaying value
  494.                         // will be set to false when the cursor moves to another video window.                                                    
  495.                                                                             
  496.                         if ((wCurrentDevice==lpDevice1->wDeviceID) && lpDevice1->bVideoPlaying)
  497.                               PlayVFWFile(hWnd,lpDevice1->hWnd,wCurrentDevice);
  498.  
  499.                         if ((wCurrentDevice==lpDevice2->wDeviceID) && lpDevice2->bVideoPlaying)
  500.                               PlayVFWFile(hWnd,lpDevice2->hWnd,wCurrentDevice);
  501.  
  502.                         if ((wCurrentDevice==lpDevice3->wDeviceID) && lpDevice3->bVideoPlaying)
  503.                               PlayVFWFile(hWnd,lpDevice3->hWnd,wCurrentDevice);
  504.  
  505.                         if ((wCurrentDevice==lpDevice4->wDeviceID) && lpDevice4->bVideoPlaying)
  506.                                PlayVFWFile(hWnd,lpDevice4->hWnd,wCurrentDevice);
  507.  
  508.                         if ((wCurrentDevice==lpDevice5->wDeviceID) && lpDevice5->bVideoPlaying)
  509.                                PlayVFWFile(hWnd,lpDevice5->hWnd,wCurrentDevice);
  510.  
  511.                         if ((wCurrentDevice==lpDevice6->wDeviceID) && lpDevice6->bVideoPlaying)
  512.                                PlayVFWFile(hWnd,lpDevice6->hWnd,wCurrentDevice);
  513.                                                                                               
  514.                         // If this is the device ID associated with the video from the initial page
  515.                         // setup the second page since we are done playing the video.
  516.                                                                                               
  517.                         if ((wCurrentDevice==lpDevice7->wDeviceID) && lpDevice7->bVideoPlaying && bIsPage0)                                 
  518.                                DoPage1();                 
  519.                               
  520.           
  521.                         return FALSE;
  522.                        }
  523.                }
  524.     break;
  525.  
  526.     case WM_DRAWITEM:             
  527.     
  528.     // The draw item message is sent when an owner draw button must be re-drawn due to a 
  529.     // mouse click, etc.  We take care of this re-drawing in the DrawControl procedure.
  530.     
  531.             DrawControl(hWnd, (LPDRAWITEMSTRUCT)lParam);
  532.     break;
  533.  
  534.     
  535.     
  536.     case WM_CLOSE:
  537.     
  538.           // When the user decides to exit the program we need to cleanup all open
  539.           // MCI devices, Window handles, global memory blocks etc.
  540.     
  541.           Cleanup();
  542.           
  543.           return FALSE;
  544.     break;
  545.     
  546.  /*   case WM_ACTIVATE:
  547.         fActive=wParam;
  548.         if (fActive==WA_INACTIVE)
  549.              if (VWRGlobal)
  550.                  {
  551.                   VwrQuit(VWRGlobal);
  552.                   VWRGlobal=0;
  553.                  }
  554.     
  555.     break;  */
  556.     
  557.     case WM_SETCURSOR: 
  558.     
  559.           // A set cursor message is sent when the cursor passes over an owner draw button.
  560.           // This is the only way I can tell if the cursor is over an owner draw button or
  561.           // not.  I do not have access to each owner draw button's window procedure so I
  562.           // trap the WM_SETCURSOR message which is sent to the parent of the Window 
  563.           // who now has the cursor.  The wParam contains the window handle of the owner
  564.           // draw button which now contains the cursor.
  565.     
  566.           if(Playback(wParam,hOld))
  567.                return TRUE;
  568.           else 
  569.                return FALSE;
  570.     break;
  571.     
  572.     // This message is sent when the main window is destroyed (DestroyWindow(hWndMain)).
  573.     
  574.     case WM_DESTROY:
  575.          PostQuitMessage( 0 );
  576.     break;
  577.     
  578.     // Let the default behaviour happen when we recieve a WM_PAINT.  
  579.     
  580.     case WM_PAINT:
  581.         
  582.         return DefWindowProc( hWnd, message, wParam, lParam );
  583.       
  584.      break;
  585.  
  586.     default:
  587.           return DefWindowProc( hWnd, message, wParam, lParam );
  588.     break;
  589.     
  590.     }
  591.     return(0L);
  592. }
  593.  
  594.  
  595. /****************************************************************************
  596.  
  597.     FUNCTION    : VideoWndProc( HWND, unsigned, WORD, LONG )
  598.  
  599.     PURPOSE   : This is the procedure for the Video Window displayed on page 2.
  600.     
  601.     COMMENTS  : This Window is used to display instructional videos for learning.  Currently nothing needs
  602.                 to be done in this procedure.  I let windows handle it all.
  603.  
  604.     HISTORY   : Created by Steven Molstad 8/5/93.
  605.  
  606. ****************************************************************************/
  607.  
  608.  
  609.  
  610. /* Procedures which make up the window class. */    
  611.  
  612. long FAR PASCAL VideoWndProc( hWnd, message, wParam, lParam )
  613. HWND hWnd;
  614. unsigned message;
  615. WORD wParam;
  616. LONG lParam;
  617. {
  618.  
  619.      switch (message)
  620.            {
  621.             case WM_CREATE:
  622.              
  623.             break;
  624.  
  625.             case WM_SYSCOMMAND:
  626.                    switch (wParam)
  627.                           {
  628.                             default:
  629.                                    return DefWindowProc( hWnd, message, wParam, lParam );
  630.  
  631.                             }
  632.              break;
  633.  
  634.              case WM_COMMAND:
  635.              break;  
  636.              
  637.              case WM_DESTROY:
  638.                    PostQuitMessage( 0 );
  639.              break;
  640.  
  641.  
  642.              default:
  643.                    return DefWindowProc( hWnd, message, wParam, lParam );
  644.               break;
  645.             }
  646.       return(0L);
  647.              
  648. }  
  649.  
  650.  /****************************************************************************
  651.  
  652.     FUNCTION  :  Transition(LPDEVICESTRUCT,int,int,int)
  653.  
  654.     PURPOSE   :  This procedure takes care of morphing and calling the routine to process the 
  655.                  next page.  
  656.  
  657.     COMMENTS  :  When transitioning between page 1 and page 2 I re-use the MCI device ID's.  That is to
  658.                  say I close the old device and re-open the new device vs leaving two devices open.
  659.                  This process conserves resource ID's.  To speed up the process of transitioning pages
  660.                  one could load all the AVI files at the start of the program and leave them open until
  661.                  the program shuts down.  I opted to conserve resources.
  662.  
  663.  
  664.     HISTORY   :  Created by Steven Molstad 8/31/93
  665.  
  666. ****************************************************************************/
  667.  
  668. BOOL FAR PASCAL Transition(lpDevice,uixPos,uiyPos,device)
  669. LPDEVICESTRUCT lpDevice;                         
  670. int uixPos;
  671. int uiyPos;
  672. int device;
  673.  
  674. {
  675.     
  676.     RECT ChildWinRect;
  677.     HDC hTempDC;
  678.     HANDLE VWR;  
  679.     char szCommand[80];
  680.     
  681.  
  682.             // The Function GetRealClientRect is used to retrieve the x,y,dx,dy position of the button.  
  683.            // The coordinates retrieved is relative to the top left corner of the client area and not
  684.            // the screen.  Therefore these coordinates are relative to what is being returned in the 
  685.            // Low and High word of lParam.
  686.                                          
  687.            GetRealClientRect(lpDevice->hWnd,hWndMain,&ChildWinRect);
  688.            
  689.            // check to see if the button was depressed while the cursor was over the owner draw button.
  690.            
  691.            if ((uixPos < ChildWinRect.right) && (uiyPos > ChildWinRect.top) && (uixPos > ChildWinRect.left) && (uiyPos < ChildWinRect.bottom) )
  692.             {
  693.             
  694.             // if the button was depressed while the cursor was over the owner draw button and this
  695.             // is page 2 do the stuff appropriate to page 2.
  696.             
  697.             if (bIsPage2 && (lpDevice->bPlayAudio || lpDevice->bPlayVideo))
  698.                  {
  699.                  
  700.                  // Different actions happen depending on which of the 4 buttons are pressed
  701.                  // on page 2.
  702.                    
  703.                   switch (device)
  704.                         {
  705.                          case 1:
  706.                                {
  707.                  
  708.                                  // Hide the Window for Device 9, the Video Window, and show the Edit Window.
  709.                    
  710.                                 ShowWindow( lpDevice9->hWnd, SW_HIDE ); 
  711.                                 
  712.                                 // we have to jump to the contents otherwise VwrCommand will not load Viewer.
  713.                                 
  714.                                 wsprintf(szCommand,"JumpContents(`%s')",lpDevice1->szFileName);  
  715.                                 
  716.                                 // grab the handle to viewer if it is already running.
  717.                                 
  718.                                 VWR = VwrFromMVB(lpDevice1->szFileName);
  719.                                 
  720.                                 // if the Viewer handle it null then run Viewer.
  721.                                 
  722.                                 VWR = VwrCommand(VWR, lpDevice1->szFileName, szCommand, cmdoptNONE);
  723.                                  
  724.                                // Get a global handle to Viewer so we can shut it down when necessary. 
  725.                                  
  726.                                 VWRGlobal = VwrFromMVB(lpDevice1->szFileName);
  727.                                
  728.                                 // we also want to hide all the buttons to avoid any nasty palette problems.
  729.                           
  730.                                 ShowWindow( lpDevice1->hWnd, SW_HIDE );   
  731.                                 ShowWindow( lpDevice2->hWnd, SW_HIDE );
  732.                                 ShowWindow( lpDevice3->hWnd, SW_HIDE );
  733.                                 ShowWindow( lpDevice4->hWnd, SW_HIDE );
  734.                                 
  735.                                 // Ensure that the Viewer window will stay on top.  The position information 
  736.                                 // doesn't position the Viewer window.  This needs to be done when authoring
  737.                                 // the Viewer title.
  738.                                 
  739.                                 SetWindowPos(VWRGlobal,(HWND) HWND_TOPMOST,Points3.left,Points3.top,Points3.right,Points3.bottom,SWP_NOACTIVATE);
  740.                                 
  741.                                 // hide the button bar.
  742.                                      
  743.                                 ShowWindow( hWndButtonBar, SW_HIDE );  
  744.                                 
  745.                                  
  746.                                 return TRUE;     
  747.                                 }
  748.                                 
  749.                          case 2:
  750.                                {       
  751.                                
  752.                    // Kill the Viewer window and show the video playback control.  Since we now hide all
  753.                    // the buttons killing the viewer window is useless.  Left in to demonstrate the command
  754.                    // only.
  755.                    
  756.                                 if (VWRGlobal)
  757.                                      {
  758.                                      VwrQuit(VWRGlobal);
  759.                                      VWRGlobal=0;
  760.                                      }
  761.                                 
  762.                                
  763.                                 ShowWindow( lpDevice9->hWnd, SW_SHOWNORMAL );  
  764.                                 ShowWindow( hWndButtonBar, SW_SHOWNORMAL ); 
  765.                                 
  766.                                  // we also want to hide all the buttons to avoid any nasty palette problems.
  767.                           
  768.                                 ShowWindow( lpDevice1->hWnd, SW_HIDE );   
  769.                                 ShowWindow( lpDevice2->hWnd, SW_HIDE );
  770.                                 ShowWindow( lpDevice3->hWnd, SW_HIDE );
  771.                                 ShowWindow( lpDevice4->hWnd, SW_HIDE );
  772.                                 
  773.                                 return TRUE;                                
  774.                    
  775.                                 }
  776.                             
  777.                          case 3:
  778.                                {   
  779.                                      
  780.                                 // hide the edit window, show the video window minimize the application and
  781.                                 // execute application specified in the ini file.
  782.                                      
  783.                                 ShowWindow( hWndEdit, SW_HIDE ); 
  784.                                 ShowWindow(lpDevice9->hWnd, SW_SHOWNORMAL );
  785.                                 
  786.                                  
  787.                                  if(lstrlen(lpDevice3->szFileName))
  788.                                       { 
  789.                                       // we have to jump to the contents otherwise VwrCommand will not load Viewer.
  790.                                 
  791.                                       wsprintf(szCommand,"JumpContents(`%s')",lpDevice3->szFileName);  
  792.                                    
  793.                                       // grab the handle to viewer if it is already running.
  794.                                 
  795.                                        VWR = VwrFromMVB(lpDevice3->szFileName);
  796.                                        
  797.                                       
  798.                                        // if the Viewer handle it null then run Viewer.
  799.                                 
  800.                                        VWR = VwrCommand(VWR, lpDevice3->szFileName, szCommand, cmdoptNONE);
  801.                                  
  802.                                        }
  803.                                        
  804.                                 SendMessage(hWndMain,WM_SYSCOMMAND,SC_MINIMIZE,0L);             
  805.                                 return TRUE;                                     
  806.                                 }
  807.                          
  808.                          case 4:
  809.                                 {  
  810.                                 
  811.                                  // hide the edit window, show the video window, minimize the application and
  812.                                  // execute application specified in the ini file.
  813.                                  
  814.                                  ShowWindow( hWndEdit, SW_HIDE );
  815.                                  ShowWindow(lpDevice9->hWnd, SW_SHOWNORMAL );                                
  816.                                   
  817.                                  if(lstrlen(lpDevice3->szFileName))
  818.                                       {  
  819.                                       // we have to jump to the contents otherwise VwrCommand will not load Viewer.
  820.                                 
  821.                                        wsprintf(szCommand,"JumpContents(`%s')",lpDevice4->szFileName);  
  822.                                   
  823.                                        // grab the handle to viewer if it is already running.
  824.                                 
  825.                                        VWR = VwrFromMVB(lpDevice4->szFileName);
  826.                                        
  827.                                       
  828.                                        // if the Viewer handle it null then run Viewer.
  829.                                 
  830.                                        VWR = VwrCommand(VWR, lpDevice4->szFileName, szCommand, cmdoptNONE);
  831.                                  
  832.                                        }    
  833.                                        
  834.                                  SendMessage(hWndMain,WM_SYSCOMMAND,SC_MINIMIZE,0L); 
  835.              
  836.                                  return TRUE;
  837.          
  838.                                  }
  839.                         }
  840.                   return TRUE;
  841.                  }      
  842.                  
  843.              // if it is the first page and Audio or Video is enabled Morph and display next page.  
  844.              // If Audio and Video are both disabled the functionality is disabled.
  845.              
  846.             if(bIsPage1 && (lpDevice->bPlayAudio || lpDevice->bPlayVideo) )
  847.              {
  848.              
  849.              // if this is page 1 set that a button was clicked and that there is no video playing.
  850.              
  851.               lpDevice->bRButtonClicked=TRUE;
  852.               lpDevice->bVideoPlaying=FALSE;
  853.               lpDevice->bAudioPlaying=FALSE;
  854.                                                   
  855.               // Reset all video windows to the first frame.                                    
  856.                                                   
  857.               SeekAllToStart();
  858.                                                             
  859.               // Since the morph Window will be displayed over the first window in this case hide window 1.
  860.               // This is not really necessary since the morph window will always be displayed ontop.                                             
  861.                                                             
  862.                   ShowWindow( lpDevice->hWnd, SW_HIDE );
  863.                    
  864.                    // This function does the processing for the morph window.
  865.                    
  866.                    
  867.                    Morph(lpDevice8,device); 
  868.                     
  869.                    //Get the Device Context for the morph window and then update the video in that window.
  870.                                                                                          
  871.                    hTempDC=GetDC(lpDevice8->hWnd);                   
  872.                    
  873.                    UpdateVFW (lpDevice8->wDeviceID,hTempDC);
  874.  
  875.                    ReleaseDC(lpDevice8->hWnd,hTempDC); 
  876.                                        
  877.                    
  878.                    // stop all wave files from playing and start a new wave file playing, the wave file
  879.                    // for device 8.
  880.                    
  881.                    StopAllWaveFiles();
  882.                                     
  883.                    if (lpDevice8->bPlayAudio)
  884.                         if (lpDevice8->wAudioDeviceID)
  885.                              PlayWaveFile(lpDevice8->wAudioDeviceID); 
  886.                              
  887.                    if (lpDevice8->bPlayVideo)     
  888.                          if (lpDevice8->wDeviceID)
  889.                                PlayVFWFileWait(hWndMain,lpDevice8->hWnd,lpDevice8->wDeviceID);
  890.                   
  891.                                   
  892.                    // Hide the morph window, close the wave file and the morph avi movie and move on to 
  893.                    // the next page.               
  894.                                   
  895.                    ShowWindow( lpDevice8->hWnd, SW_HIDE );
  896.  
  897.                    
  898.                    if (lpDevice8->wAudioDeviceID)
  899.                           CloseWaveFile(lpDevice8->wAudioDeviceID);
  900.  
  901.                    
  902.                    
  903.                    if (lpDevice8->wDeviceID)
  904.                         CloseVFWFile(lpDevice8->wDeviceID);
  905.  
  906.  
  907.                    DoNextPage(device);
  908.                  
  909.  
  910.             
  911.              } // if bIsPage1 
  912.                                     
  913.                                     
  914.              // if both audio and video are disabled in the ini file then do nothing and display a dialog
  915.              // box stating that the functionality has been disabled.                       
  916.                                     
  917.              if ((!lpDevice->bPlayAudio && !lpDevice->bPlayVideo))
  918.                      MessageBox(hWndMain,"Functionality Disabled","DISABLED",MB_OK);       
  919.             
  920.         return TRUE;
  921.         }    
  922.                            
  923. return FALSE;
  924. }
  925.